package com.novel.system.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import com.novel.common.utils.StreamUtils;
import com.novel.common.utils.StringUtils;
import com.novel.framework.annotation.Log;
import com.novel.framework.base.BaseController;
import com.novel.framework.enums.BusinessType;
import com.novel.framework.redis.ICacheService;
import com.novel.framework.result.Result;
import com.novel.framework.web.page.TableDataInfo;
import com.novel.system.domain.SysUserOnline;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.novel.common.constants.Constants.LOGIN_TOKEN_KEY;
import static com.novel.common.constants.Constants.ONLINE_TOKEN_KEY;

/**
 * 在线用户监控
 *
 * @author novel
 * @since 2019/12/20
 */
@RestController
@RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController {
    private final ICacheService iCacheService;

    public SysUserOnlineController(ICacheService iCacheService) {
        this.iCacheService = iCacheService;
    }

    /**
     * 在线用户列表
     *
     * @param ipaddr   查询条件，ip地址
     * @param userName 查询条件，用户名
     * @return 在线用户列表
     */
    @SaCheckPermission("monitor:online:list")
    @GetMapping("/list")
    public TableDataInfo list(String ipaddr, String userName) {

        // 获取所有未过期的 token
        List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
        List<SysUserOnline> userOnlineList = new ArrayList<>();
        for (String key : keys) {
            String token = key.replace(LOGIN_TOKEN_KEY, "");
            // 如果已经过期则跳过
            if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < -1) {
                continue;
            }
            userOnlineList.add(iCacheService.get(ONLINE_TOKEN_KEY + token));
        }


        if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
            userOnlineList = StreamUtils.filter(userOnlineList, userOnline ->
                    StringUtils.contains(userOnline.getIpaddr(), ipaddr) &&
                            StringUtils.contains(userOnline.getLoginName(), userName)
            );
        } else if (StringUtils.isNotEmpty(ipaddr)) {
            userOnlineList = StreamUtils.filter(userOnlineList, userOnline ->
                    StringUtils.contains(userOnline.getIpaddr(), ipaddr)
            );
        } else if (StringUtils.isNotEmpty(userName)) {
            userOnlineList = StreamUtils.filter(userOnlineList, userOnline ->
                    StringUtils.contains(userOnline.getLoginName(), userName)
            );
        }
        userOnlineList.sort((o1, o2) -> o2.getStartTimestamp().compareTo(o1.getStartTimestamp()));
        userOnlineList.removeAll(Collections.singleton(null));
        return getDataTable(userOnlineList);
    }

    /**
     * 强退用户
     *
     * @param tokenId 用户会话id
     * @return 强退结果
     */
    @SaCheckPermission("monitor:online:forceLogout")
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
    @DeleteMapping("/{tokenId}")
    public Result forceLogout(@PathVariable("tokenId") String tokenId) {
        try {
            StpUtil.kickoutByTokenValue(tokenId);
        } catch (NotLoginException ignored) {
        }
        return success();
    }
}
